using System;
using System.IO;
using System.IO.Compression;

namespace Jonathan.SharpDB
{
    /// <summary>
    /// Static methods for compressing and decompressing bytes...
    /// </summary>
    public class Compressor
    {
        #region - Compress -

        /// <summary>
        /// Compresses an array of bytes using gzip...
        /// </summary>
        /// <param name="buffer">Uncompressed Array of Bytes.</param>
        /// <returns>Compressed Array of Bytes.</returns>
        public static byte[] Compress(byte[] buffer)
        {
            MemoryStream ms = new MemoryStream();
            GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true);
            zip.Write(buffer, 0, buffer.Length);
            zip.Close();
            ms.Position = 0;

            return ms.ToArray();
        }

        #endregion

        #region - Decompress -

        /// <summary>
        /// Decompressed a gzip-ed array of bytes...
        /// </summary>
        /// <param name="gzBuffer">Compressed Array of Bytes.</param>
        /// <returns>Uncompressed Array of Bytes.</returns>
        public static byte[] Decompress(byte[] gzBuffer)
        {
            // Load Compressed bytes into Memory Stream...
            MemoryStream ms = new MemoryStream(gzBuffer);
            // Create a memory stream from uncompressed bytes...
            MemoryStream msR = new MemoryStream();

            // Move position to 0...
            ms.Position = 0;

            // Create a new GZip stream from compressed bytes...
            GZipStream zip = new GZipStream(ms, CompressionMode.Decompress);
            
            // Create a buffer to hold decompressed data...
            byte[] buffer = new byte[512];
            while (true)
            {
                // Read decompressed data...
                int read = zip.Read(buffer, 0, 512);
                if (read == 0)
                {
                    return msR.ToArray();
                }

                // Write data...
                msR.Write(buffer, 0, read);
            }
        }

        #endregion
    }
}
